const { getRandomRange } = require('./utils');
class Game {
	constructor(roomName, state) {
		this.roomIndex = roomName;
		this.state = state;
		this.gameMsg = '初始化游戏中';
		// name sid deskIndex
		this.players = [];
		// 存已经准备好的玩家座位号
		this.readyPlayer = [];
		this.winner = null;
		this.activePlayer = getRandomRange(0, 2);
		// 隐藏分类型
		this.keyScores = [];
		// 剩余卡牌
		this.restCards = [];
		// 弃牌区
		this.deadCards = [];
		// 手牌区
		this.handCards = [];
		// 隐藏分 [2,3,4],[],[]
		this.hiddenScores = [];
		// 牌面分 [1,5,7],[],[]
		this.obviousScores = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
		// 正在交易的卡
		this.tradeCards = [];
		// 记录三个玩家手中的明牌 [[],[],[]]
		this.seeCards = [];
		// 处于冷却中的明牌
		this.banCrad = [];
		// 可看见隐藏分类型
		this.seeHiddenScore = [[false, false, false], [false, false, false], [false, false, false]]
	}
	shufferCards() {
		let cards = [];
		for (let j = 0; j <= 2; j++) {
			let tmp = [];
			for (let i = 1; i < 10; i++) {
				tmp.push(i + j * 10);
			}
			cards.push(tmp);
		}

		// 随机产生隐藏分类型
		for (let i = 0; i <= 2; i++) {
			let curType = getRandomRange(0, 2)
			this.keyScores.push(curType);
		}
		console.log(this.keyScores);
		for (let j = 1; j <= 3; j++) {
			// 逆时针 [1] 的隐藏分类型 即是玩家 0 的初始手牌类型
			let cur = [];
			switch (this.keyScores[j % 3]) {
				// 注意优先级问题
				case 0:
					cur.push(...(cards[0].splice(getRandomRange(0, cards[0].length - 1), 1)));
					cur.push(...(cards[1].splice(getRandomRange(0, cards[1].length - 1), 1)));
					cur.push(...(cards[1].splice(getRandomRange(0, cards[1].length - 1), 1)));
					cur.push(...(cards[2].splice(getRandomRange(0, cards[2].length - 1), 1)));
					cur.push(...(cards[2].splice(getRandomRange(0, cards[2].length - 1), 1)));
					break;
				case 1:
					cur.push(...(cards[0].splice(getRandomRange(0, cards[0].length - 1), 1)));
					cur.push(...(cards[0].splice(getRandomRange(0, cards[0].length - 1), 1)));
					cur.push(...(cards[1].splice(getRandomRange(0, cards[1].length - 1), 1)));
					cur.push(...(cards[2].splice(getRandomRange(0, cards[2].length - 1), 1)));
					cur.push(...(cards[2].splice(getRandomRange(0, cards[2].length - 1), 1)));
					break;
				case 2:
					cur.push(...(cards[0].splice(getRandomRange(0, cards[0].length - 1), 1)));
					cur.push(...(cards[0].splice(getRandomRange(0, cards[0].length - 1), 1)));
					cur.push(...(cards[1].splice(getRandomRange(0, cards[1].length - 1), 1)));
					cur.push(...(cards[1].splice(getRandomRange(0, cards[1].length - 1), 1)));
					cur.push(...(cards[2].splice(getRandomRange(0, cards[2].length - 1), 1)));
					break;
				default:
					break;
			}
			this.handCards.push(cur);
		}
		this.restCards = [...cards[0], ...cards[1], ...cards[2]]
		this.restCards.splice(getRandomRange(0, this.restCards.length - 1), 0, 10);
		this.restCards.splice(getRandomRange(0, this.restCards.length - 1), 0, 20);
		this.restCards.splice(getRandomRange(0, this.restCards.length - 1), 0, 30);
	}
	get roomIndex() {
		return this.roomIndex;
	}
	get players() {
		return this.players;
	}
	getPlayerSids() {
		return this.players.map(e => e.sid);
	}
	getHandCard(i) {
		return this.handCards[i]
	}
	getRestCard() {
		return this.restCards.splice(getRandomRange(0, this.restCards.length - 1), 1)
	}
	getRestCardLength() {
		return this.restCards.length
	}
	getDeadCardLength() {
		return this.deadCards.length
	}
	getDeadCard() {
		return this.deadCards
	}
	get activePlayer() {
		return this.activePlayer;
	}
	get state() {
		return this.state;
	}
	get gameMsg() {
		return this.gameMsg;
	}
	getPrevPlayerHiddenScore(myindex) {
		let prev = (myindex + 2) % 3;
		return this.hiddenScores[prev];
	}
	getHiddenScore(type) {
		if (type > -1) {
			// 固定返回当前活跃玩家的某一花色隐藏分
			return this.hiddenScores[this.activePlayer][type];
		} else {
			return this.hiddenScores
		}
	}
	get banCard() {
		return this.banCrad;
	}
	getSeeHiddenScore(i) {
		// 返回某位玩家的隐藏分是否可见的布尔值数组衍生的隐藏分
		let res = [0, 0, 0];
		for (let j = 0; j < this.seeHiddenScore[i].length; j++) {
			if (this.seeHiddenScore[i][j]) {
				res[j] = this.hiddenScores[i][j];
			}
		}
		return res;
	}
	getSeeCards(i) {
		if (i == 0) {
			return [this.seeCards[1], this.seeCards[2]]
		} else if (i == 1) {
			return [this.seeCards[2], this.seeCards[0]]
		} else if (i == 2) {
			return [this.seeCards[0], this.seeCards[1]]
		} else {
			console.log("重连玩家获取其他人的明牌信息出错了");
		}
	}
	addSeeCard(i, card) {
		if (!this.seeCards[i]) {
			this.seeCards[i] = []
		}
		this.seeCards[i].push(card);
	}
	removeBanCard(i) {
		this.banCrad.splice(this.banCrad.indexOf(i), 1);
	}
	addBanCard(i) {
		this.banCrad.push(i);
	}
	set state(state) {
		this.state = state
	}
	turnToNextPlayer() {
		this.activePlayer = (this.activePlayer + 1) % 3;
	}
	addPlayer(player) {
		this.players.push(player);
	}
	removePlayer(deskIndex) {
		this.players.splice(deskIndex, 1);
	}
	genDeadCard() {
		console.log("触发演化");
		if (this.restCards.length > 0) {
			// 演化 从抽牌堆取一张放到弃牌堆中 返回弃牌堆最上面一张
			let card = this.getRestCard();
			if (card[0] % 10 == 0) {
				this.deadCards = [];
				// 触发了万能牌进入弃牌堆时，弃牌堆清零，给个卡背给玩家看
				return 31;
			}
			this.deadCards.push(card[0]);
			return card[0];
		}
		return -1;
	}
	playGame(action, deskIndex, params) {
		let cardType = null;
		if ((typeof params != 'object') && (typeof params != 'undefined') && (params > -1)) {
			cardType = Math.floor((params - (params % 10 == 0 ? 1 : 0)) / 10);
		}
		let res = null;
		let card = null;
		let nextPlayerIndex = (this.activePlayer + 1) % 3;
		let prevPlayerIndex = (this.activePlayer + 2) % 3;
		switch (action) {
			case 'consume':
				this.gameMsg = `${this.players[deskIndex].name}打出${cardType}类型的卡${params}`;
				params = parseInt(params);
				this.obviousScores[deskIndex][cardType] += (params % 10);
				// 从手牌中移除
				this.removeCard(deskIndex, params);
				res = this.calcTotalScores(deskIndex);
				break;
			case 'deliver':
				this.gameMsg = `${this.players[deskIndex].name}发起交易${cardType}类型的卡${params}`;
				this.tradeCards[0] = parseInt(params);
				// 从手牌中移除
				this.removeCard(deskIndex, params);
				break;
			case 'draw':
				// 从抽牌堆里抓一张，放到手牌中，当前函数返回抓到的那张牌
				card = this.getRestCard()[0];
				cardType = Math.floor((card - (card % 10 == 0 ? 1 : 0)) / 10);
				// 默认没有触发得分
				let flag = false;
				for (let i = 0; i < this.handCards[deskIndex].length; i++) {
					const e = this.handCards[deskIndex][i];
					if (Math.floor((e - (e % 10 == 0 ? 1 : 0)) / 10) == cardType) {
						// 有同类型的牌
						if (e > card) {
							// 且大于抽到的牌
							flag = true;
						}
						break;
					} else {
						// 发现手牌中没有同类型的牌
						if (i == (this.handCards[deskIndex].length - 1)) {
							flag = true;
						}
					}
				}
				if (flag) {
					this.obviousScores[deskIndex][cardType] += (card % 10);
					res = [card, ...this.calcTotalScores(deskIndex)];
					this.gameMsg = `${this.players[deskIndex].name}抽牌得分${cardType}类型的卡${card}`;
				} else {
					// 没有触发得分，那么抽到的牌加入手牌中
					this.handCards[deskIndex].push(card);
					res = card;
					this.gameMsg = `${this.players[deskIndex].name}抽到了一张牌`;
				}
				break;
			case 'decompose':
				// 从弃牌堆里拿顶上一张
				card = this.getDeadCard().pop();
				cardType = Math.floor((card - (card % 10 == 0 ? 1 : 0)) / 10);
				this.gameMsg = `${this.players[deskIndex].name}从弃牌堆打出了${cardType}类型的卡${card}`;
				this.obviousScores[deskIndex][cardType] += (card % 10);
				res = this.calcTotalScores(deskIndex);
				break;
			case 'request':
				if ((params[0] % 10 == 0) || ((params[0] % 10) >= (params[1] % 10))) {
					this.gameMsg = `${this.players[deskIndex].name}用${params[0]}强制交易了卡${params[1]}`;
					// 我的交易牌为万能牌或者 > 别人的明牌,可以交易
					let tradePlayer = null;
					cardType = Math.floor((params[1] - (params[1] % 10 == 0 ? 1 : 0)) / 10);
					// 找到该明牌
					if (this.handCards[prevPlayerIndex].indexOf(parseInt(params[1])) > -1) {
						tradePlayer = prevPlayerIndex;
					} else if (this.handCards[nextPlayerIndex].indexOf(parseInt(params[1])) > -1) {
						tradePlayer = nextPlayerIndex;
					}
					if (tradePlayer != null) {
						// 接收交易方移除他的明牌
						this.removeCard(tradePlayer, params[1]);
						let newCard = null;
						if (params[0] % 10 == 0) {
							newCard = parseInt(params[0]) - getRandomRange(2, 8)
							// 如果我这张是万能牌，则在进入下家手牌时，变化
							this.handCards[tradePlayer].push(newCard);
						} else {
							this.handCards[tradePlayer].push(parseInt(params[0]));
						}
						// 发起交易方从手牌移除交易牌
						this.removeCard(this.activePlayer, params[0]);

						this.obviousScores[this.activePlayer][cardType] += (parseInt(params[1]) % 10);

						res = [...(this.calcTotalScores(this.activePlayer)), tradePlayer, newCard > 0 ? newCard : null];
					}
				} else {
					res = false;
				}
				break;
			case 'trade':
				this.tradeCards[1] = parseInt(params);
				this.tradeCards[0] = parseInt(this.tradeCards[0]);
				// 下家回传交易牌的类型
				let nextCardType = cardType;
				// 保存上家的交易牌类型
				cardType = Math.floor((this.tradeCards[0] - (this.tradeCards[0] % 10 == 0 ? 1 : 0)) / 10);
				this.gameMsg = `${this.players[deskIndex].name}回应交易了${nextCardType}类型的卡${this.tradeCards[1]}`;
				console.log(this.gameMsg);
				if ((this.tradeCards[1] % 10 == 0) || ((this.tradeCards[0] % 10) < (this.tradeCards[1] % 10))) {
					// 发起交易的玩家失去他的交易牌,已经在发起交易时从手牌移除了
					this.gameMsg = `${this.players[deskIndex].name}白嫖了${cardType}类型的卡${this.tradeCards[0]}`;
					// 万能牌变为随机一张 2-8 的明牌
					if (this.tradeCards[1] % 10 == 0) {
						// 记住万能牌在接收交易玩家手牌中的位置
						let index = this.handCards[nextPlayerIndex].indexOf(this.tradeCards[1]);
						if (index > -1) {
							// 减去 2-8 即可
							this.tradeCards[1] -= getRandomRange(2, 8);
							// 该玩家手牌中的万能牌变为随机牌
							this.handCards[nextPlayerIndex][index] = this.tradeCards[1];
						}
					}
					// 触发白嫖,下家吃牌,接受交易的玩家,加分,明牌
					this.obviousScores[nextPlayerIndex][cardType] += (this.tradeCards[0] % 10);
					res = [nextPlayerIndex, ...(this.calcTotalScores(nextPlayerIndex)), ...(this.tradeCards)];
					// 明牌进入冷却中队列
					this.addBanCard(this.tradeCards[1]);
					// 记住下家手中的明牌,只有在触发下家吃牌时才会产生明牌
					this.addSeeCard(nextPlayerIndex, this.tradeCards[1])
				} else {
					// 回应交易时，当前的活动玩家还是发起交易的玩家
					if (this.hiddenScores[this.activePlayer][cardType] > this.hiddenScores[nextPlayerIndex][cardType]) {
						// 触发剥削成功,接受交易的玩家,失去交易牌,但得到上家的交易牌
						this.removeCard(nextPlayerIndex, params);
						this.handCards[nextPlayerIndex].push(this.tradeCards[0]);
						// 发起交易的玩家,加分
						this.obviousScores[this.activePlayer][nextCardType] += (this.tradeCards[1] % 10);
						res = [this.activePlayer, ...this.calcTotalScores(this.activePlayer), this.tradeCards[0]];
						this.gameMsg = `${this.players[this.activePlayer].name}剥削了${nextCardType}类型的卡${this.tradeCards[1]}`;
					} else {
						// 双方交换交易牌
						// 从手牌中移除
						this.removeCard(nextPlayerIndex, params);
						// 在发起交易时已经移除了,所以这里只需再添加
						this.handCards[this.activePlayer].push(this.tradeCards[1]);
						this.handCards[nextPlayerIndex].push(this.tradeCards[0]);
						res = [...(this.tradeCards)];
						// 记录玩家可见的隐藏分
						this.seeHiddenScore[this.activePlayer][nextCardType] = true;
						this.gameMsg = `暗中交易,未触发吃牌,发起交易方看到自己的隐藏分,类型取决于接收交易方传的牌的类型`;
					}
				}
				this.tradeCards = [];
				break;
			default:
				break;
		}
		console.log(this.gameMsg);
		return res;
	}
	calcHiddenScore() {
		for (let i = 0; i < this.handCards.length; i++) {
			const cards = this.handCards[i];
			let tmp = [];
			if (cards[1] < 10) {
				tmp[0] = Math.min(cards[0], cards[1]);
				if (cards[3] < 20) {
					tmp[1] = Math.min(cards[2] - 10, cards[3] - 10);
					tmp[2] = (cards[4] - 20) * 2;
				} else {
					tmp[1] = (cards[2] - 10) * 2;
					tmp[2] = Math.min(cards[3] - 20, cards[4] - 20);
				}
			} else {
				tmp[0] = cards[0] * 2;
				tmp[1] = Math.min(cards[1] - 10, cards[2] - 10);
				tmp[2] = Math.min(cards[3] - 20, cards[4] - 20);
			}
			this.hiddenScores.push(tmp);
		}
		let tmp = this.hiddenScores.shift();
		this.hiddenScores.push(tmp);
	}
	calcTotalScores(i) {
		// input 玩家在桌子上的编号
		// output 赢->[赢的类型,玩家三项总分] 没赢->[-1,玩家三项牌面分]
		let res = [-1];
		for (let j = 0; j < 3; j++) {
			const oneTypeScore = this.hiddenScores[i][j] + this.obviousScores[i][j];
			if (oneTypeScore >= 30) {
				res[0] = j;
				this.winner = this.players[i];
				this.state = 'winner produced';
			}
			res.push(oneTypeScore);
		}
		if (res[0] > -1) {
			return res;
		} else {
			return [-1, ...(this.obviousScores[i])];
		}
	}
	removeCard(deskIndex, card) {
		card = parseInt(card);
		this.handCards[deskIndex].splice(this.handCards[deskIndex].indexOf(card), 1);
		if (this.seeCards.length > 0) {
			if (deskIndex < this.seeCards.length && this.seeCards[deskIndex]) {
				if (this.seeCards[deskIndex].indexOf(card) > -1) {
					// 移除卡时，如果该卡是明牌，则记住该明牌已消失
					this.seeCards[deskIndex].splice(this.seeCards[deskIndex].indexOf(card), 1)
				}
			}
		}
	}
	ready(i) {
		this.readyPlayer.push(i);
		if (this.readyPlayer.length == 3) {
			this.readyPlayer = [];
			return true;
		} else {
			return false;
		}
	}
	reset() {
		this.gameMsg = '初始化游戏中';
		this.winner = null;
		this.activePlayer = getRandomRange(0, 2);
		// 隐藏分类型
		this.keyScores = [];
		// 剩余卡牌
		this.restCards = [];
		// 弃牌区
		this.deadCards = [];
		// 手牌区
		this.handCards = [];
		// 隐藏分 [2,3,4],[],[]
		this.hiddenScores = [];
		// 牌面分 [1,5,7],[],[]
		this.obviousScores = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
		// 正在交易的卡
		this.tradeCards = [];
		// 记录三个玩家手中的明牌 [[],[],[]]
		this.seeCards = [];
		// 处于冷却中的明牌
		this.banCrad = [];
		// 可看见隐藏分类型
		this.seeHiddenScore = [[false, false, false], [false, false, false], [false, false, false]]
	}
}
module.exports = Game;
